#include "gtest/gtest.h"
#include <mutex>
#include <condition_variable>
#include <thread>
#include <atomic>
#include <chrono>

#include "stream/Topic.h"
#include "stream/Appender.h"
#include "stream/Reader.h"

using namespace stream;

//static void cbAppend(std::shared_ptr<Topic> & topic, std::atomic<bool> & isRunning, std::mutex & mutex, std::condition_variable & dataAppended){
//    printf("start appender...\n");
//
//    auto writer = std::shared_ptr<Appender>(::stream::makeAppender(topic));
//    writer->open(); 
//
//    for(size_t count = 0; count < 100; ++count){
//        if(count % 10 == 0){
//            std::this_thread::sleep_for (std::chrono::milliseconds(10));
//            printf("appended thread sleep 100ms: count:%zu\n", count);
//        }
//        std::unique_lock lock(mutex);
//        writer->append(count, "GTP" + std::to_string(count+1));
//        dataAppended.notify_all();
//        printf("append GTP--%zu\n", count+1);
//    }
//    writer->close();
//
//    printf("append finished\n");
//    isRunning.store(false, std::memory_order_seq_cst);
//}

//1. Single Appender Only 
// see: TestAppender.cpp: TEST(AppenderTest, test)
//2. Single Reader Only 
// see: TestReaderWrapper.cpp: TEST_F(ReaderWrapperTest, testSequenceReader)

//3. Single Appender (thread) & Single Reader (thread)
TEST(FunctionTest, testAppenderReader){
//    std::atomic<bool> isRunning(true); // for reader loop exit
//    std::mutex mutex;       // for data Appended Event (condition_variable) notify & wait
//    std::condition_variable dataAppended; //data Appended Event fired
//
//    //1. new topic
//    auto topic = std::shared_ptr<Topic>(::stream::makeTopic("hello", "."));
//
//    //2. start append thread : new appender, loop-append(with cond notify), 
//    std::thread thread(cbAppend, std::ref(topic), std::ref(isRunning), std::ref(mutex), std::ref(dataAppended));
//
//    //3. new reader 
//    auto reader = std::shared_ptr<Reader>(::stream::makeReader(topic, 0));
//    reader->open();
//
//    //4. read loop: exit-condition:  isRunning ==false && reader can not read data
//    while(isRunning.load() || reader->hasNext()){
//        //4.1 read all data in topic
//        while(reader->hasNext()){
//            printf("read :%s\n", reader->current()->c_str());
//            reader->next();
//        }
//        //4.2 wait data append thread produce data
//        {
//            std::unique_lock lock(mutex);
//            auto ret = dataAppended.wait_for(lock, std::chrono::milliseconds(20));
//            //4.2.1 if no data in 100ms, wait_for timeout: for exit check(isRunning == false)
//            if(ret == std::cv_status::timeout){
//                printf("wait_for dataAppended event Timeout\n");
//            }
//            //4.2.2 if data appended notified => reader->hasNext() == true ; continue read data
//            else{
//                printf("wait_for dataAppended event Fired\n");
//            }
//        }
//    }
//    printf("reader finished\n");
//    //4.3 resource clear
//    reader->close();
//    thread.join(); 
}
